package ms.core.serv.system;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.*;

import ms.core.common.*;
import ms.core.common.consts.SysErr;
import ms.core.common.utils.*;
import ms.core.serv.dto.Api;
import ms.core.serv.system.LWGAuthorization.LWGAuth;
import ms.core.serv.tool.*;
import ms.core.tool.*;

public class CoreServlet extends HttpServlet{
	private static final long serialVersionUID = 4099217125937243494L;

	private Object call(HttpServletRequest req, HttpServletResponse resp) {
		String fn = req.getParameter("fn");
		Map<String, Object> body = RequestUtils.getJsonBody(req);

		// 判断调用接口有效性
		Api api = ApiLoader.getApi(fn);
		if (api==null)
			return new ApiResult(false, SysErr.SYS_UNKNOWN_FUNC, "未知接口调用");

		// 判断访问者IP是否是授权的
		String ip = RequestUtils.getRequestRemoteIp(req);
		if (!WhiteIpLoader.legalIp(ip)) 
			return new ApiResult(false, SysErr.SYS_ACCESS_FORBID, "非授权IP访问");

		// 判断访问者鉴权信息
		if (api.isAuth()) {
			LWGAuth auth = JsonTool.objectToBean(req.getHeader("auth"), LWGAuth.class);
			if (auth==null)
				return new ApiResult(false, SysErr.SYS_ACCESS_FORBID, "未授权访问!");
			
			if (!LWGAuthorization.checkAuth(auth.getT(), auth.getSign()))
				return new ApiResult(false, SysErr.SYS_SIGNATURE_ERR, "签名错误");
		}

		try {
			if (Application.appDelegate!=null) Application.appDelegate.beforeCallApi(api);

			Class<?> cls=Class.forName(api.getClassName());
			Method method = cls.getMethod(api.getFunctionName(), HttpServletRequest.class, HttpServletResponse.class, Map.class);
			//接口调用
			return method.invoke(cls.newInstance(), req, resp, body);
		} catch(Exception e) {
			Throwable targetEx = e.getCause();
			if (targetEx==null) targetEx = e;
			if (targetEx instanceof AppException) {
				return new ApiResult(false, ((AppException) targetEx).getCode(), ((AppException) targetEx).getMsg());
			} else {
				Log4j2Tool.error(CoreServlet.class, "API调用异常", e);
				return new ApiResult(false, SysErr.SYS_UNKNOWN_ERR);
			}
		} finally {
			if (Application.appDelegate!=null) Application.appDelegate.afterCallApi(api);
		}
	}

	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Object ret = call(req, resp);
		if (ret instanceof ApiResult)
			ResponseUtils.doResponse(resp, 200, (ApiResult)ret);
		else if (ret instanceof byte[])
			ResponseUtils.doResponse(resp, 200, (byte[]) ret);
		else
			ResponseUtils.doResponse(resp, 200, ret==null ? "" : ret.toString());
    }

	@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Object ret = call(req, resp);
		if (ret instanceof ApiResult)
			ResponseUtils.doResponse(resp, 200, (ApiResult)ret);
		else if (ret instanceof byte[])
			ResponseUtils.doResponse(resp, 200, (byte[]) ret);
		else
			ResponseUtils.doResponse(resp, 200, ret==null ? "" : ret.toString());
	}
}
